#!-*-coding: utf-8 -*-
"""
服务器
"""
from socket import *
from select import select
import struct, pickle
from messageutil import *
from protocol import *
from dbutil import *
from room import *
from game21 import *
from threading import Timer
from threading import Thread

_host = ""
_port = 18888

_game21_interval = 10  # 21点游戏, 游戏间隔为5分钟, 为了方便调试, 没有按照要求选择半点


class Server:
    def __init__(self):
        self.__host = _host
        self.__port = _port
        self.__init_server()
        self.__msg_head_len = MESSAGE_HEAD_LENGTH
        self.__sock_user_dict = {}  # 用户socket和该用户之间的映射
        self.__user_sock_dict = {}
        self.__username_user_dict = {}
        self.__db_util = DbUtil()   # 数据库操作
        self.__func_dict = {}   # 协议号和对应的处理函数之间的映射
        self.__init_func_dict()
        # 房间相关
        self.__user_room_dict = {}
        self.__roomname_room_dict = {}
        # game21
        self.__room_game21_dict = {}
        self.__game_thread = Thread(target=self.__game21_func)

    def __init_func_dict(self):
        """
        desc:   初始化映射协议号和对应的协议处理函数
        """
        self.__func_dict[REGISTER_REQ] = self.__deal_register_req
        self.__func_dict[LOGIN_REQ] = self.__deal_login_req
        self.__func_dict[LOGOUT_REQ] = self.__deal_logout_req
        self.__func_dict[PRIVATE_CHAT_REQ] = self.__deal_char_to_req
        self.__func_dict[ROOM_CHAT_REQ] = self.__deal_chat_room_req
        self.__func_dict[WORLD_CHAT_REQ] = self.__deal_chat_world_req
        self.__func_dict[CREATE_ROOM_REQ] = self.__deal_create_room_req
        self.__func_dict[ENTER_ROOM_REQ] = self.__deal_enter_room_req
        self.__func_dict[LEAVE_ROOM_REQ] = self.__deal_leave_room_req
        self.__func_dict[QUERY_ROOM_LIST_REQ] = self.__deal_query_room_list_req
        self.__func_dict[SEND_GAME21_EXPRESSION_REQ] = self.__deal_send_game21_expression_req

    def __init_server(self):
        """
        desc:   初始化服务器socket
        """
        self.__sock = socket(AF_INET, SOCK_STREAM)
        #self.__sock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
        self.__sock.bind((self.__host, self.__port))
        self.__sock.listen(0)   # 不限制可以连接的客户端数量
        self.__main_socks = []  # 仅包含服务器socket
        self.__main_socks.append(self.__sock)
        self.__read_socks = []  # 保存服务器socket和连接的客户端socket
        self.__read_socks.append(self.__sock)

    def __del__(self):
        # 服务端关闭时, 关闭所有的客户端连接
        for sock in self.__read_socks:
            sock.close()

    def start(self):
        """
        desc:   启动服务器接受客户端连接, 使用select来提高并发量
        param:  空
        return  空
        """
        self.__game_thread.start()  # 启动21点游戏线程
        while True:
            readable_socks, writable_socks, exceptions = select(self.__read_socks, [], [])
            for sock in readable_socks:
                if sock in self.__main_socks:
                    # 将新的连接加入到socket连接列表中
                    new_sock, addr = sock.accept()
                    self.__read_socks.append(new_sock)
                else:
                    msg_head = 0
                    try:
                        # 读取消息头(消息体的长度)
                        msg_head = self.__recv_data(sock, self.__msg_head_len)
                    # sock对应的client强制关闭时，会触发该异常
                    except Exception as ex:
                        # 将客户端用户下线, 关闭客户端socket连接
                        self.__user_offline(sock)
                        self.__close_sock(sock)
                        # print(("错误信息:" + ex.message).decode("utf-8"))
                        continue
                    # msg_head = -1表示，client正常关闭，接收到的数据大小为0
                    if msg_head == -1:
                        self.__user_offline(sock)
                        self.__close_sock(sock)
                    else:
                        # 解析消息头, 对应消息体的长度
                        msg_body_len = parse_head(msg_head)
                        # 根据消息头包含的消息体长度
                        msg_body = self.__recv_data(sock, msg_body_len)
                        # 反序列化消息体, 获得字典数据
                        msg = parse_body(msg_body)
                        # print("Received Message:",msg)
                        #try:
                        # 处理消息体, 如果有确认消息, 则msg为该请求对应的确认消息, 否则为None
                        ack_msg = self.__deal_recv_data(msg, sock)
                        if ack_msg:
                            # print(ack_msg)
                            # 如果ack_msg不为空, 那么说明此次客户端请求有确认信息, 需要发送给客户端
                            sock.send(pack_msg(ack_msg))
                        #发送消息时, 出现错误表示用户已经意外断开
                        '''except:
                            self.__user_offline(sock)
                            self.__close_sock(sock)'''

    def __close_sock(self, sock):
        """
        desc:   关闭客户端socket连接
        param:
            sock:   待关闭的客户端socket
        return  空
        """
        sock.close()
        # 从连接的客户端socket列表中删除该socket
        self.__read_socks.remove(sock)

    def __recv_data(self, sock, recv_len):
        """
        desc:	接收服务器发送的指定长度的数据
        param:
            recv_len:	接收数据的长度
        return:
        recv_data:	指定长度的来自于服务器的数据
        """
        recv_data = ""
        recv_data_len = 0
        while recv_data_len < recv_len:
            remain_len = recv_len - recv_data_len
            tmp_recv_data = sock.recv(remain_len)
            if not tmp_recv_data:
                return -1

            recv_data += tmp_recv_data
            recv_data_len += len(tmp_recv_data)

        return recv_data

    def __user_login(self, dict_data, src_sock):
        """
        desc:   用户登录, 构建socket和该用户之间的映射
        param:
            dict_data:  用户登录请求中包含的消息(字典)
            sock:   发送请求的客户端sokcet
        return  空
        """
        user_name = dict_data["name"]
        # 构建User对象
        user = User(user_name, self.__db_util)
        # 用户和socket之间的映射
        self.__sock_user_dict[src_sock] = user
        self.__user_sock_dict[user] = src_sock
        # 根据用户登录的username建立和user对象的映射, 避免用户重复登录
        self.__username_user_dict[user_name] = user

        # 通知所有在线用户, 该user上线
        msg_context = "用户:" + user_name + "上线!"
        self.__system_world_msg_inform(msg_context, src_sock)

    def __user_offline(self, src_sock):
        """
        desc:   用户下线
        param:
            sock:   待下线的客户端sokcet
        return  空
        """
        # 若用户还未登录, 调用__user_offline会出错, 因此需要做出判断
        if src_sock not in self.__sock_user_dict:
            return
        user = self.__sock_user_dict[src_sock]
        user_name = user.get_user_name()
        self.__sock_user_dict.pop(src_sock)
        self.__user_sock_dict.pop(user)
        self.__username_user_dict.pop(user_name)
        user.off_line() # 用户下线
        # 如果该用户在房间中, 需要先退出房间
        if user in self.__user_room_dict.keys():
            self.__leave_room(user)
        # 通知所有在线用户, 该user下线
        msg_context = "用户:" + user_name + "下线!"
        self.__system_world_msg_inform(msg_context, src_sock)

    def __inform_user_not_login(self, src_sock):
        """
        desc:   通知用户暂未登录
        param:
            sock:   客户端sokcet
        return  空
        """
        msg = {}
        msg["option"] = SYSTEM_MSG_INFORM
        msg["ret"] = ERROR_NOT_LOGIN
        src_sock.send(pack_msg(msg))

    def __deal_recv_data(self, dict_data, src_sock):
        """
        desc:   处理服务器接收的数据
        param:
            dict_data:  解析后的客户端数据
            sock:   客户端sokcet
        return:
            dict: 确认消息, 如果该请求没有确认消息, 那么返回None
        """
        option = dict_data["option"]
        # 如果当前请求不是注册或者登录, 而且该socket没有用户登录的话,
        # 那么通知客户端还未登录
        if option != REGISTER_REQ and option != LOGIN_REQ:
            if src_sock not in self.__sock_user_dict:
                self.__inform_user_not_login(src_sock)
                return
        # 根据请求类型, 获取对应的请求处理函数
        deal_func = self.__func_dict[option]
        res = deal_func(dict_data, src_sock)
        return res

    def __deal_register_req(self, dict_data, src_sock):
        """
        desc:   处理客户端注册请求
        param:
            dict_data:  解析后的客户端数据
            sock:   客户端sokcet
        return:
            dict: 请求对应的确认消息
        """
        user_name = dict_data["name"]
        user_pwd = dict_data["pwd"]
        ack_msg = {}
        ack_msg["option"] = REGISTER_ACK
        # 用户名已经注册过
        if self.__db_util.has_user_name(user_name):
            ack_msg["ret"] = ERROR_NAME_HAS_BEEN_REGISTERED
        # 成功注册
        else:
            ack_msg["ret"] = SUCCESS_OPERATION
            self.__db_util.register_user(user_name, user_pwd)
        return ack_msg

    def __deal_login_req(self, dict_data, src_sock):
        """
        desc:   处理客户端登录请求
        param:
            dict_data:  解析后的客户端数据
            sock:   客户端sokcet
        return:
            dict: 请求对应的确认消息
        """
        user_name = dict_data["name"]
        user_pwd = dict_data["pwd"]
        res = {}
        res["option"] = LOGIN_ACK
        # 数据库中没有该用户名
        if not self.__db_util.has_user_name(user_name):
            res["ret"] = ERROR_NAME_NOT_EXIST
        # 一个连接只能同时登录一个账号
        elif src_sock in self.__sock_user_dict.keys():
            res["ret"] = ERROR_REPEAT_LOGIN
        # 该用户名已经登录
        elif user_name in self.__username_user_dict:
            res["ret"] = ERROR_SUCH_USER_NAME_HAS_BEEN_LOGINED
        # 登录成功
        elif self.__db_util.can_login(user_name, user_pwd):
            res["ret"] = SUCCESS_OPERATION
            self.__user_login(dict_data, src_sock)
        # 密码错误
        else:
            res["ret"] = ERROR_PWD
        return res

    def __deal_logout_req(self, dict_data, src_sock):
        """
        desc:   处理客户端登出请求
        param:
            dict_data:  解析后的客户端数据
            src_sock:   客户端sokcet
        return:
            dict: 请求对应的确认消息
        """
        res = {}
        res["option"] = LOGOUT_ACK
        # 未登录
        if src_sock not in self.__sock_user_dict.keys():
            res["ret"] = ERROR_NOT_LOGIN
        else:
            self.__user_offline(src_sock)   # 下线
            res["ret"] = SUCCESS_OPERATION
        return res

    def __deal_chat_world_req(self, dict_data, src_sock):
        """
        desc:   处理客户端世界聊天请求
        param:
            dict_data:  解析后的客户端数据
            src_sock:   客户端sokcet
        return:
            dict: 请求对应的确认消息
        """
        user = self.__sock_user_dict[src_sock]
        msg_context = dict_data["context"]
        ack_msg = {}
        ack_msg["option"] = WORLD_CHAT_ACK
        ack_msg["ret"] = SUCCESS_OPERATION
        # src_sock.send(pack_msg(ack_msg))

        transfer_msg = {}
        transfer_msg["option"] = WORLD_CHAT_MSG_TRANSFER
        transfer_msg["peername"] = user.get_user_name()
        transfer_msg["context"] = msg_context
        # 向所有在线用户发送该消息内容
        for sock in self.__sock_user_dict.keys():
            if sock is src_sock:
                continue
            sock.send(pack_msg(transfer_msg))

        return ack_msg

    def __deal_char_to_req(self, dict_data, src_sock):
        """
        desc:   处理客户端私人聊天请求
        param:
            dict_data:  解析后的客户端数据
            src_sock:   客户端sokcet
        return:
            dict: 请求对应的确认消息
        """
        src_user = self.__sock_user_dict[src_sock]
        msg_context = dict_data["context"]
        dst_user_name = dict_data["peername"]
        ack_msg = {}
        ack_msg["option"] = PRIVATE_CHAT_ACK
        # 私聊对象不存在
        if not self.__db_util.has_user_name(dst_user_name):
            ack_msg["ret"] = ERROR_PEER_NAME_NOT_EXIST
        # 私聊对象未上线
        elif dst_user_name not in self.__username_user_dict.keys():
            ack_msg["ret"] = ERROR_PEER_NOT_ONLINE
        # 不能私聊自己
        elif dst_user_name == src_user.get_user_name():
            ack_msg["ret"] = ERROR_PRIVATE_CHAT_TO_SELF
        else:
            # 发送私人消息
            dst_user = self.__username_user_dict[dst_user_name]
            ack_msg["ret"] = SUCCESS_OPERATION
            transfer_msg = {}
            transfer_msg["option"] = PRIVATE_CHAT_MSG_TRANSFER
            transfer_msg["peername"] = src_user.get_user_name()
            transfer_msg["context"] = msg_context
            dst_sock = self.__user_sock_dict[dst_user]
            dst_sock.send(pack_msg(transfer_msg))
        # src_sock.send(pack_msg(ack_msg))
        return ack_msg

    def __deal_chat_room_req(self, dict_data, src_sock):
        """
        desc:   处理客户端房间聊天请求
        param:
            dict_data:  解析后的客户端数据
            src_sock:   客户端sokcet
        return:
            dict: 请求对应的确认消息
        """
        ack_msg = {}
        ack_msg["option"] = ROOM_CHAT_ACK
        user = self.__sock_user_dict[src_sock]
        if user not in self.__user_room_dict.keys():
            ack_msg["ret"] = ERROR_NOT_IN_ROOM
        else:
            ack_msg["ret"] = SUCCESS_OPERATION
            #src_sock.send(pack_msg(ack_msg))
            transfer_msg = {}
            transfer_msg["option"] = ROOM_CHAT_MSG_TRANSFER
            transfer_msg["peername"] = user.get_user_name()
            transfer_msg["context"] = dict_data["context"]
            room = self.__user_room_dict[user]
            for member in room.get_members():
                if member != user:
                    sock = self.__user_sock_dict[member]
                    sock.send(pack_msg(transfer_msg))
        return ack_msg


    def __system_world_msg_inform(self, context, src_scok):
        """
        desc:   对所有在线用户发送系统消息
        param:
            context:  待发送的系统消息
            src_sock:   如果为None, 表示系统消息, 所有在线用户都会收到,
                        不是None, 那么src_sock对应的客户端不能收到该消息(例如上线
                        时, 上线者不需要收到该提醒)
        return:
            dict: 请求对应的确认消息
        """
        msg = {}
        msg["option"] = SYSTEM_MSG_INFORM
        msg["context"] = "[系统]" + context
        for sock in self.__sock_user_dict.keys():
            if sock != src_scok:
                sock.send(pack_msg(msg))

    def __system_room_msg_inform(self, context, room, send_user):
        """
        desc:   对房间成员发送系统消息
        param:
            context:  待发送的系统消息
            src_sock:   如果为None, 表示系统消息, 所有在线用户都会收到,
                        不是None, 那么src_sock对应的客户端不能收到该消息(例如加入房间
                        时, 加入者不需要收到该提醒)
        return:
            dict: 请求对应的确认消息
        """
        # 如果send_user不是None, 那么该消息是send_user发送的, 该消息不可以发送给send_user
        room_members = room.get_members()
        send_sock = None
        msg_context = context
        # 获取send_user对应的socket
        if send_user != None and send_user in self.__user_sock_dict.keys():
            send_sock = self.__user_sock_dict[send_user]
        msg_context = "[系统]" + msg_context
        msg = {}
        msg["option"] = SYSTEM_MSG_INFORM
        msg["context"] = msg_context
        for member in room_members:
            if member in self.__user_sock_dict.keys():
                member_sock = self.__user_sock_dict[member]
                if member_sock != send_sock:
                    member_sock.send(pack_msg(msg))

    def __create_room(self, user, room_name):
        """
        desc:   创建房间涉及的逻辑
        param:
            user:  房间创建者
            room_name:   创建的房间名
        return:
            int: 创建房间的状态码
        """
        # 用户已在房间中
        if user in self.__user_room_dict.keys():
            return ERROR_HAVE_BEEN_IN_ROOM
        # 房间名已存在
        elif room_name in self.__roomname_room_dict.keys():
            return ERROR_EXISTED_ROOM_NAME
        room = Room(user, room_name)
        self.__roomname_room_dict[room_name] = room
        self.__user_room_dict[user] = room
        #context = "创建房间成功!"
        #self.__system_room_msg_inform(context, room)
        # 房间创建时, 建立room->game21映射
        self.__room_game21_dict[room] = Game21()
        return SUCCESS_OPERATION

    def __deal_create_room_req(self, dict_data, src_sock):
        """
        desc:   处理创建房间请求
        param:
            dict_data:  解析后的客户端数据
            src_sock:   客户端sokcet
        return:
            dict: 请求对应的确认消息
        """
        user = self.__sock_user_dict[src_sock]
        room_name = dict_data["room_name"]
        ack_msg = {}
        ack_msg["option"] = CREATE_ROOM_ACK
        ret = self.__create_room(user, room_name)
        ack_msg["ret"] = ret
        return ack_msg

    def __enter_room(self, user, room_name):
        """
        desc:   进入房间涉及的逻辑
        param:
            user:  进入房间者
            room_name:   进入的房间名
        return:
            int: 进入房间的状态码
        """
        # 避免重复进入房间(已经在其他房间中)
        if user in self.__user_room_dict.keys():
            return ERROR_REPEAT_ENTER_ROOM
        # 房间名不存在
        elif room_name not in self.__roomname_room_dict:
            return ERROR_ROOM_NAME_NOT_EXIST
        else:
            room = self.__roomname_room_dict[room_name]
            # 已经在要加入的房间中
            if room.has_user(user):
                return ERROR_HAVE_BEEN_IN_ROOM
            else:
                room.add_user(user)
                self.__user_room_dict[user] = room
                user_name = user.get_user_name()
                context = user_name + "加入房间!"
                self.__system_room_msg_inform(context, room, user)
                return SUCCESS_OPERATION

    def __deal_enter_room_req(self, dict_data, src_sock):
        """
        desc:   处理进入房间请求
        param:
            dict_data:  解析后的客户端数据
            src_sock:   客户端sokcet
        return:
            dict: 请求对应的确认消息
        """
        room_name = dict_data["room_name"]
        user = self.__sock_user_dict[src_sock]
        ack_msg = {}
        ack_msg["option"] = ENTER_ROOM_ACK
        ret = self.__enter_room(user, room_name)
        ack_msg["ret"] = ret
        return ack_msg

    def __leave_room(self, user):
        """
        desc:   离开房间涉及的逻辑
        param:
            user:  离开房间者
        return:
            int: 离开房间的状态码
        """
        if user in self.__user_room_dict.keys():# room.has_user(user):
            room = self.__user_room_dict[user]
            # 房间只有一个用户时, 删除该房间
            if room.member_count() == 1:
                self.__delete_room(room)
            else:
                room.remove_member(user)
                self.__user_room_dict.pop(user)
                user_name = user.get_user_name()
                context = user_name + "离开房间!"
                # 通知其他房间成员, 该用户离开房间
                self.__system_room_msg_inform(context, room, user)
            return SUCCESS_OPERATION
        # 用户不在房间中
        else:
            return ERROR_NOT_IN_ROOM


    def __deal_leave_room_req(self, dict_data, src_sock):
        """
        desc:   处理离开房间请求
        param:
            dict_data:  解析后的客户端数据
            src_sock:   客户端sokcet
        return:
            dict: 请求对应的确认消息
        """
        #room_name = dict_data["room_name"]
        user = self.__sock_user_dict[src_sock]
        room = self.__user_room_dict[user]
        room_name = room.get_name()
        ack_msg = {}
        ack_msg["option"] = LEAVE_ROOM_ACK
        ret = self.__leave_room(user)
        ack_msg["ret"] = ret
        return ack_msg

    def __delete_room(self, room):
        """
        desc:   删除房间涉及的逻辑
        param:
            room:  删除的房间
        return:
            int: 删除房间的状态码
        """
        room_name = room.get_name()
        msg_context = "房间:%s解散!" % room_name
        room_members = room.get_members()
        self.__system_room_msg_inform(msg_context, room, None)
        # 通知房间的所有成员, 房间要被解散(现有的逻辑是最后一个人离开房间时,房间才会解散)
        for member in room_members:
            self.__user_room_dict.pop(member)
        self.__roomname_room_dict.pop(room_name)
        # 解散房间时, 需要将room->game21的映射删除
        self.__room_game21_dict.pop(room)

    def __query_room_list(self):
        """
        desc:   请求房间列表涉及的逻辑
        param:
            room:  删除的房间
        return:
            int: 删除房间的状态码
        """
        room_list = []
        for room in self.__roomname_room_dict.values():
            tmp = {}
            tmp["room_name"] = room.get_name()
            tmp["room_member_num"] = room.member_count()
            room_list.append(tmp)
        return room_list

    def __deal_query_room_list_req(self, dict_data, src_sock):
        """
        desc:   处理查询房间列表请求
        param:
            dict_data:  解析后的客户端数据
            src_sock:   客户端sokcet
        return:
            dict: 请求对应的确认消息
        """
        ack_msg = {}
        ack_msg["option"] = QUERY_ROOM_LIST_ACK
        ack_msg["ret"] = SUCCESS_OPERATION
        room_list = self.__query_room_list()
        ack_msg["room_list"] = room_list
        return ack_msg

    def __deal_send_game21_expression_req(self, dict_data, src_sock):
        """
        desc:   处理用户发送的21点游戏答案请求
        param:
            dict_data:  解析后的客户端数据
            src_sock:   客户端sokcet
        return:
            dict: 请求对应的确认消息
        """
        ack_msg = {}
        ack_msg["option"] = SEND_GAME21_EXPRESSION_ACK
        ack_msg["ret"] = SUCCESS_OPERATION
        ack_msg["context"] = ""
        user = self.__sock_user_dict[src_sock]
        # 用户未加入任意房间
        if user not in self.__user_room_dict.keys():
            ack_msg["ret"] = ERROR_GAME_NOT_IN_ROOM
            return ack_msg
        room = self.__user_room_dict[user]
        game21 = self.__room_game21_dict[room]
        # 当前不是21点游戏时间
        if not game21.is_running():
            ack_msg["ret"] = ERROR_NOT_IN_GAME_TIME
            return ack_msg
        room = self.__user_room_dict[user]
        game21 = self.__room_game21_dict[room]
        answer = dict_data["expression"]
        try:
            game21.add_player(user.get_user_name(), answer)
            ack_msg["context"] = "[系统]成功参加游戏, %d秒后系统会通知赢家!" % int(game21.get_remain_time())
        # 当前不是21点游戏时间(这一句其实并不需要)
        except ErrorNotInGameTime:
            ack_msg["ret"] = ERROR_NOT_IN_GAME_TIME
        # 发送的答案里有非法字符
        except ErrorInvalidCharacter:
            ack_msg["ret"] = ERROR_GAME_INVALID_CHARACTER
        # 发送的答案不是正确的数学式子
        except ErrorInvalidExpression:
            ack_msg["ret"] = ERROR_GAME_INVLAID_EXPRESSION
        return ack_msg

    # 游戏结束时, 调用该方法获得game21的赢家, 并通知房间的所有成员
    def __inform_game21_winner(self, room):
        """
        desc:   每个房间通知21点游戏获胜者
        param:
            room:  待处理的房间
        return: 空
        """
        # 在21点游戏期间, 需要考虑房间解散的情况
        if room not in self.__room_game21_dict.keys():
            return
        game21 = self.__room_game21_dict[room]
        winner_name = game21.get_winner_name()
        ack_context = ""
        # 没有人参与或者未正确参与
        if winner_name == None:
            ack_context = "此轮21点游戏没有胜者!"
        else:
            ack_context = "此轮21点游戏的胜者是:" + winner_name
        # 通知房间所有成员, 21点游戏获胜者
        self.__system_room_msg_inform(ack_context, room, None)

    def __game21_func(self):
        """
        desc:   21点游戏线程
        param:  空
        return: 空
        """
        while True:
            # 通知每个房间所有成员, 21点游戏将要开始
            ready_time = 10
            for (room, game21) in self.__room_game21_dict.items():
                context = "21点游戏将会在%d秒后开始!" % ready_time
                self.__system_room_msg_inform(context, room , None)
            time.sleep(ready_time)

            # 每个房间启动21点游戏
            game21_last_time = 0
            for (room, game21) in self.__room_game21_dict.items():
                # 两次游戏之间的间隔不能小于游戏的持续时间
                game21_last_time = max(game21.get_last_time(), game21_last_time)
                game21.start()  #开始每个房间的21点游戏
                expression = game21.get_given_num() # 获取21点游戏的数字
                # 通知房间成员21点游戏开始, 并告知21点游戏的给定数字
                context = "21点游戏开始, 给定的4个数字为:" + str(expression)
                self.__system_room_msg_inform(context, room , None)
                # 启动定时器, 游戏结束时通知获胜者
                timer = Timer(game21_last_time - 1, self.__inform_game21_winner, (room,))
                timer.start()
            interval_time = max(game21_last_time, _game21_interval)
            time.sleep(interval_time)
            # print(time.ctime(time.time()))


if __name__ == "__main__":
    s = Server()
    s.start()
